#include <iostream>
#include <source_location>
// 注意：GCC 13的标准库可能不完全支持std::stacktrace，即使头文件存在
// 这里强制禁用，避免编译错误
// 如果需要使用stacktrace，需要安装libstdc++-exp并链接stdc++exp库
#define HAS_STACKTRACE 0
// #ifdef __has_include
//   #if __has_include(<stacktrace>)
//     #include <stacktrace>
//     #define HAS_STACKTRACE 1
//   #else
//     #define HAS_STACKTRACE 0
//   #endif
// #else
//     #define HAS_STACKTRACE 0
// #endif
#include <string>
#include <vector>
#include <stdexcept>

namespace cpp23 {

// 利用std::stacktrace记录当前函数调用
void log_current_stacktrace(const std::string& message) {
    std::cout << "日志消息: " << message << "\n";
    
#if HAS_STACKTRACE
    // 获取当前的堆栈跟踪
    auto trace = std::stacktrace::current();
    
    std::cout << "堆栈跟踪 (" << trace.size() << " 帧):\n";
    for (size_t i = 0; i < trace.size(); ++i) {
        const auto& frame = trace[i];
        std::cout << "  [" << i << "] ";
        
        // 尝试获取函数名和源码位置信息
        if (frame.description().empty()) {
            std::cout << "未知函数";
        } else {
            std::cout << frame.description();
        }
        
        // 尝试获取源文件和行号
        const auto src_loc = frame.source_location();
        if (src_loc.line() > 0) {
            std::cout << " at " << src_loc.file_name() << ":" << src_loc.line();
        }
        
        std::cout << "\n";
    }
    std::cout << "\n";
#else
    std::cout << "  注意：std::stacktrace在当前编译器/标准库中不可用\n";
    std::cout << "  请使用GCC 12+并链接libstdc++exp库以启用此功能\n\n";
#endif
}

// 使用std::source_location获取当前的源代码位置
void log_with_location(const std::string& message,
                       const std::source_location& location = std::source_location::current()) {
    std::cout << "位置: " << location.file_name() << ":" << location.line() 
              << " (函数: " << location.function_name() << ")\n";
    std::cout << "消息: " << message << "\n\n";
}

// 示例递归函数，用于演示堆栈跟踪
int factorial(int n) {
    if (n <= 1) {
        // 在基本情况下记录堆栈
        log_current_stacktrace("到达阶乘的基本情况");
        return 1;
    }
    return n * factorial(n - 1);
}

// 用于演示多级函数调用的堆栈跟踪
void function_c() {
    log_current_stacktrace("在function_c内部");
    log_with_location("function_c执行中");
}

void function_b() {
    log_with_location("调用function_c前");
    function_c();
    log_with_location("function_c返回后");
}

void function_a() {
    log_with_location("调用function_b前");
    function_b();
    log_with_location("function_b返回后");
}

// 演示捕获和存储堆栈跟踪
class ErrorWithStacktrace {
private:
    std::string m_message;
#if HAS_STACKTRACE
    std::stacktrace m_trace;
#endif

public:
    ErrorWithStacktrace(const std::string& message)
        : m_message(message)
#if HAS_STACKTRACE
        , m_trace(std::stacktrace::current())
#endif
    {}

    void print_details() const {
        std::cout << "错误: " << m_message << "\n";
#if HAS_STACKTRACE
        std::cout << "发生时的堆栈跟踪:\n" << m_trace << "\n";
#else
        std::cout << "注意：std::stacktrace在当前环境中不可用\n";
#endif
    }
};

// 用于演示异常中的堆栈跟踪
void unsafe_operation() {
    throw ErrorWithStacktrace("在unsafe_operation中发生错误");
}

void caller_function() {
    try {
        unsafe_operation();
    } catch (const ErrorWithStacktrace& e) {
        std::cout << "捕获到异常...\n";
        e.print_details();
    }
}

// 演示堆栈跟踪的工具函数
void print_nested_stacktrace(int depth) {
    if (depth <= 0) {
#if HAS_STACKTRACE
        auto trace = std::stacktrace::current();
        std::cout << "嵌套深度 " << depth << " 的堆栈:\n" << trace << "\n";
#else
        std::cout << "嵌套深度 " << depth << " 的堆栈: std::stacktrace不可用\n";
#endif
        return;
    }
    print_nested_stacktrace(depth - 1);
}

// 用于比较当前C++标准中的调试功能
void compare_debug_features() {
    std::cout << "C++标准中的调试功能比较:\n";
    std::cout << "=======================\n";
    
    std::cout << "1. C++11: __func__ 宏\n";
    std::cout << "   当前函数名: " << __func__ << "\n\n";
    
    std::cout << "2. C++17: std::source_location\n";
    auto loc = std::source_location::current();
    std::cout << "   文件: " << loc.file_name() << "\n";
    std::cout << "   行号: " << loc.line() << "\n";
    std::cout << "   函数: " << loc.function_name() << "\n";
    std::cout << "   列号: " << loc.column() << "\n\n";
    
    std::cout << "3. C++23: std::stacktrace\n";
#if HAS_STACKTRACE
    auto trace = std::stacktrace::current();
    std::cout << "   堆栈帧数: " << trace.size() << "\n";
    std::cout << "   示例格式化输出: \n" << trace << "\n";
#else
    std::cout << "   std::stacktrace在当前环境中不可用\n";
#endif
}

// 一个简单的函数，用于展示堆栈跟踪
void print_current_stacktrace() {
  std::cout << "当前堆栈跟踪:" << std::endl;
#if HAS_STACKTRACE
  std::cout << std::stacktrace::current() << std::endl;
#else
  std::cout << "std::stacktrace在当前环境中不可用" << std::endl;
#endif
}

// 一个递归函数，用于创建深层堆栈
void recursive_function(int depth) {
  if (depth <= 0) {
    std::cout << "递归终点，输出堆栈:" << std::endl;
#if HAS_STACKTRACE
    auto trace = std::stacktrace::current();
    
    std::cout << "堆栈帧数: " << trace.size() << std::endl;
    
    // 打印完整堆栈
    std::cout << trace << std::endl;
    
    // 也可以逐一打印堆栈帧
    std::cout << "\n逐帧分析:" << std::endl;
    for (size_t i = 0; i < trace.size(); ++i) {
      const auto& frame = trace[i];
      std::cout << "帧 " << i << ": " 
                << frame.description();
      const auto src_loc = frame.source_location();
      if (src_loc.line() > 0) {
        std::cout << " at " << src_loc.file_name() << ":" 
                  << src_loc.line();
      }
      std::cout << std::endl;
    }
#else
    std::cout << "std::stacktrace在当前环境中不可用" << std::endl;
#endif
    return;
  }
  
  // 递归调用以创建更深的堆栈
  recursive_function(depth - 1);
}

// 抛出带有堆栈跟踪的异常
void throw_with_stacktrace() {
  try {
    // 故意抛出一个异常
    throw std::runtime_error("示例异常");
  } catch (const std::exception& e) {
    // 捕获异常并附加堆栈跟踪信息
    std::cerr << "捕获到异常: " << e.what() << std::endl;
    std::cerr << "堆栈跟踪: " << std::endl;
#if HAS_STACKTRACE
    std::cerr << std::stacktrace::current() << std::endl;
#else
    std::cerr << "std::stacktrace在当前环境中不可用" << std::endl;
#endif
    
    // 重新抛出带有堆栈信息的异常
    throw;
  }
}

// 获取特定帧的信息
void examine_frame() {
#if HAS_STACKTRACE
  auto trace = std::stacktrace::current();
  
  if (!trace.empty()) {
    auto frame = trace[0]; // 当前帧
    
    std::cout << "当前帧信息:" << std::endl;
    std::cout << "描述: " << frame.description() << std::endl;
    const auto src_loc = frame.source_location();
    if (src_loc.line() > 0) {
      std::cout << "源文件: " << src_loc.file_name() << std::endl;
      std::cout << "行号: " << src_loc.line() << std::endl;
    }
    std::cout << "地址: " << frame.native_handle() << std::endl;
  }
#else
  std::cout << "当前帧信息: std::stacktrace在当前环境中不可用" << std::endl;
#endif
}

// 比较两个堆栈跟踪
void compare_stacktraces() {
#if HAS_STACKTRACE
  // 捕获第一个堆栈跟踪
  auto trace1 = std::stacktrace::current();
  
  // 做一些其他操作并捕获第二个堆栈跟踪
  int dummy = 0;
  for (int i = 0; i < 10; ++i) {
    dummy += i;
  }
  auto trace2 = std::stacktrace::current();
  
  // 比较两个堆栈跟踪
  if (trace1 == trace2) {
    std::cout << "两个堆栈跟踪相同" << std::endl;
  } else {
    std::cout << "两个堆栈跟踪不同" << std::endl;
    std::cout << "差异:" << std::endl;
    
    // 显示不同帧
    size_t min_size = std::min(trace1.size(), trace2.size());
    for (size_t i = 0; i < min_size; ++i) {
      if (trace1[i] != trace2[i]) {
        std::cout << "帧 " << i << " 不同:" << std::endl;
        std::cout << "  trace1: " << trace1[i].description() << std::endl;
        std::cout << "  trace2: " << trace2[i].description() << std::endl;
      }
    }
    
    // 处理一个堆栈比另一个长的情况
    if (trace1.size() > trace2.size()) {
      std::cout << "trace1 有 " << (trace1.size() - trace2.size()) 
                << " 个额外帧" << std::endl;
    } else if (trace2.size() > trace1.size()) {
      std::cout << "trace2 有 " << (trace2.size() - trace1.size()) 
                << " 个额外帧" << std::endl;
    }
  }
#else
  std::cout << "比较堆栈跟踪: std::stacktrace在当前环境中不可用" << std::endl;
#endif
}

// 示例：使用堆栈跟踪进行日志记录
class Logger {
public:
  enum class Level { DEBUG, INFO, WARNING, ERROR };
  
  static void log(Level level, const std::string& message) {
    const char* level_str = "UNKNOWN";
    switch (level) {
      case Level::DEBUG: level_str = "DEBUG"; break;
      case Level::INFO: level_str = "INFO"; break;
      case Level::WARNING: level_str = "WARNING"; break;
      case Level::ERROR: level_str = "ERROR"; break;
    }
    
    std::cout << "[" << level_str << "] " << message << std::endl;
    
    // 错误日志附加堆栈跟踪
    if (level == Level::ERROR) {
      std::cout << "堆栈跟踪:" << std::endl;
#if HAS_STACKTRACE
      std::cout << std::stacktrace::current() << std::endl;
#else
      std::cout << "std::stacktrace在当前环境中不可用" << std::endl;
#endif
    }
  }
};

// 演示所有堆栈跟踪功能
void demonstrate_stacktrace() {
  std::cout << "C++23 堆栈跟踪 (std::stacktrace) 演示\n";
  std::cout << "=========================================\n\n";
  
  std::cout << "1. 基本堆栈跟踪:\n";
  print_current_stacktrace();
  std::cout << "\n";
  
  std::cout << "2. 函数调用链中的堆栈跟踪:\n";
  function_a();
  std::cout << "\n";
  
  std::cout << "3. 递归调用中的堆栈跟踪 (深度3):\n";
  recursive_function(3);
  std::cout << "\n";
  
  std::cout << "4. 检查特定堆栈帧:\n";
  examine_frame();
  std::cout << "\n";
  
  std::cout << "5. 比较堆栈跟踪:\n";
  compare_stacktraces();
  std::cout << "\n";
  
  std::cout << "6. 在日志中使用堆栈跟踪:\n";
  Logger::log(Logger::Level::INFO, "这是一条普通信息");
  Logger::log(Logger::Level::ERROR, "这是一个错误，将显示堆栈跟踪");
  std::cout << "\n";
  
  std::cout << "7. 异常处理中的堆栈跟踪:\n";
  try {
    throw_with_stacktrace();
  } catch (const std::exception& e) {
    std::cout << "主函数捕获到异常: " << e.what() << std::endl;
  }
  
  std::cout << "\nC++23 堆栈跟踪的优势:\n";
  std::cout << "1. 提高调试效率 - 准确定位问题发生位置\n";
  std::cout << "2. 增强错误报告 - 提供上下文信息\n";
  std::cout << "3. 标准化 - 不再依赖平台特定实现\n";
  std::cout << "4. 日志增强 - 自动记录调用上下文\n";
  std::cout << "5. 提高可诊断性 - 特别是对于生产环境问题\n";
}

} // namespace cpp23

// 主要的示范入口点
void demonstrate_stacktrace() {
    cpp23::demonstrate_stacktrace();
} 